from flask import Blueprint, render_template, request, jsonify, current_app
from flask_login import login_required, current_user
from ..services.book_service import BookService
from ..models import BorrowRecord, db,ReturnRequest
from datetime import datetime
from sqlalchemy.exc import IntegrityError
import json
bp = Blueprint('main', __name__)


@bp.route('/')
def index():
    """首页路由，带Redis访问计数器"""
    try:
        redis_client = current_app.redis_client
        # 使用Redis管道提高性能
        with redis_client.pipeline() as pipe:
            pipe.incr('global:visit_counter')
            pipe.incr(f'user:visits:{current_user.id}') if current_user.is_authenticated else None
            visit_count, *_ = pipe.execute()

        # 缓存热门书籍数据
        cached_books = redis_client.get('cache:popular_books')
        if not cached_books:
            popular_books = BookService.get_popular_books(limit=5)
            redis_client.setex('cache:popular_books', 3600, json.dumps(popular_books))  # 1小时缓存
        else:
            popular_books = json.loads(cached_books)

        return render_template(
            'index.html',
            visit_count=visit_count,
            popular_books=popular_books
        )
    except Exception as e:
        current_app.logger.error(f"首页加载失败: {str(e)}")
        return render_template('index.html', visit_count=0, popular_books=[])


@bp.route('/profile')
@login_required
def profile():
    """用户个人资料页，带缓存优化"""
    try:
        redis_client = current_app.redis_client
        profile_key = f'user:profile:{current_user.id}'

        # 检查缓存
        cached_profile = redis_client.get(profile_key)
        if cached_profile:
            return render_template('profile.html', profile_data=json.loads(cached_profile))

        # 数据库查询
        profile_data = {
            'borrow_history': BookService.get_borrow_history(current_user.id),
            'favorite_categories': BookService.get_user_preferences(current_user.id)
        }

        # 设置缓存（5分钟TTL）
        redis_client.setex(profile_key, 300, json.dumps(profile_data))
        return render_template('profile.html', profile_data=profile_data)

    except Exception as e:
        current_app.logger.error(f"个人资料加载失败: {str(e)}")
        return render_template('profile.html', profile_data={})

# 添加导出路由
@bp.route('/borrowed/export', methods=['GET'])
@login_required
def export_borrowed_books():
    """导出借阅记录，带操作频率限制"""
    try:
        redis_client = current_app.redis_client
        export_key = f'user:export:{current_user.id}'

        # 检查导出频率（每小时最多3次）
        if int(redis_client.get(export_key) or 0) >= 3:
            return jsonify({
                "success": False,
                "message": "导出操作过于频繁，请稍后再试"
            }), 429

        records = BookService.get_borrowed_books(current_user.id)

        # 记录导出操作
        redis_client.incr(export_key)
        redis_client.expire(export_key, 3600)  # 1小时窗口

        # 实际导出逻辑应放在这里
        # export_file = generate_export_file(records)

        return jsonify({
            "success": True,
            "url": "/exports/borrowed.xlsx",
            "expires_in": 3600  # 下载链接有效期
        })
    except Exception as e:
        current_app.logger.error(f"导出失败: {str(e)}")
        return jsonify({"success": False, "message": str(e)}), 500
# 添加通知路由
@bp.route('/notifications/unread', methods=['GET'])
@login_required
def get_unread_notifications():
    """获取未读通知，带实时推送支持"""
    try:
        redis_client = current_app.redis_client
        notifications_key = f'user:notifications:{current_user.id}'

        # 检查是否有新通知（使用Redis发布/订阅机制）
        last_check = float(request.args.get('since', 0))
        new_count = redis_client.zcount(notifications_key, f'({last_check}', '+inf')

        if new_count > 0:
            # 获取新通知
            notifications = redis_client.zrangebyscore(
                notifications_key,
                f'({last_check}',
                '+inf',
                withscores=True
            )
            formatted = [
                {'id': n[0], 'timestamp': n[1], 'content': json.loads(n[0])}
                for n in notifications
            ]
            return jsonify(formatted)

        return jsonify([])
    except Exception as e:
        current_app.logger.error(f"通知获取失败: {str(e)}")
        return jsonify({"success": False, "message": str(e)}), 500

@bp.route('/request_return', methods=['POST'])
@login_required
def request_return():
    record_id = request.json.get('record_id')
    # 这里添加通知管理员的逻辑
    # 可以创建一个新的Notification模型来存储这些请求
    return jsonify(success=True, message="归还申请已提交")


@bp.route('/book/return', methods=['POST'])
@login_required
def return_book():
    try:
        if not request.is_json:
            return jsonify({
                'success': False,
                'message': '请求必须为JSON格式'
            }), 400

        data = request.get_json()
        record_id = data.get('recordId')

        if not record_id:
            return jsonify({
                'success': False,
                'message': '缺少recordId参数'
            }), 400

        # 获取借阅记录
        record = BorrowRecord.query.filter_by(
            id=record_id,
            user_id=current_user.id
        ).first()

        if not record:
            return jsonify({
                'success': False,
                'message': '借阅记录不存在或不属于当前用户'
            }), 404

        if record.status != 'borrowed':
            return jsonify({
                'success': False,
                'message': f'当前状态为{record.status}，无法申请归还'
            }), 400

        # 检查是否已有待处理的归还申请
        existing_request = ReturnRequest.query.filter_by(
            record_id=record.id,
            status='pending'
        ).first()

        if existing_request:
            return jsonify({
                'success': False,
                'message': '该记录已有待处理的归还申请'
            }), 400

        # 创建归还申请
        return_request = ReturnRequest(
            record_id=record.id,
            user_id=current_user.id,
            status='pending',
            request_time=datetime.utcnow()
        )

        # 更新借阅记录状态
        record.status = 'returning'

        db.session.add(return_request)
        db.session.commit()

        return jsonify({
            'success': True,
            'message': '归还申请已提交，等待管理员处理'
        })

    except IntegrityError as e:
        db.session.rollback()
        return jsonify({
            'success': False,
            'message': '数据库完整性错误',
            'detail': str(e)
        }), 400

    except Exception as e:
        db.session.rollback()
        return jsonify({
            'success': False,
            'message': '服务器内部错误',
            'detail': str(e)
        }), 500


